#include "Brush_ex.h"

HEXBRUSH _brush_create(EXARGB argb)
{
	D2D1_COLOR_F color = {};
	ARGB2ColorF(argb, &color);
	HEXBRUSH hBrush = nullptr;
	g_Ri.pD2DDeviceContext->CreateSolidColorBrush(color, (ID2D1SolidColorBrush**)&hBrush);
	return hBrush;
}

BOOL _brush_destroy(HEXBRUSH hBrush)
{
	INT nError = 0;
	if (hBrush != 0)
	{
		nError = ((ID2D1SolidColorBrush*)hBrush)->Release();
	}
	return nError==0;
}

EXARGB _brush_setcolor(HEXBRUSH hBrush, EXARGB argb)
{
	D2D1_COLOR_F newColor = {};
	ARGB2ColorF(argb, &newColor);
	D2D1_COLOR_F oldColor = ((ID2D1SolidColorBrush*)hBrush)->GetColor();
	EXARGB retColor = 0;
	ColorF2ARGB(oldColor, &retColor);
	((ID2D1SolidColorBrush*)hBrush)->SetColor(newColor);
	return retColor;
}

HEXBRUSH _brush_createfromimg(HEXIMAGE hImg)
{
	img_s* pImg = nullptr;
	INT nError = 0;
	ID2D1BitmapBrush* hBrush = nullptr;
	if (_handle_validate(hImg, HT_IMAGE, (LPVOID*)&pImg, &nError))
	{
		LPVOID pObj = pImg->pObj_;
		ID2D1Bitmap* pBitmap = nullptr;
		HRESULT hr = g_Ri.pD2DDeviceContext->CreateBitmapFromWicBitmap((IWICBitmapSource*)pObj, &pBitmap);
		if (hr == 0)
		{
			D2D1_BITMAP_BRUSH_PROPERTIES pro2 = {};
			pro2.extendModeX = D2D1_EXTEND_MODE_WRAP;
			pro2.extendModeY = D2D1_EXTEND_MODE_WRAP;
			pro2.interpolationMode = D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR;
			g_Ri.pD2DDeviceContext->CreateBitmapBrush(pBitmap, pro2, &hBrush);
		}
		pBitmap->Release();
	}
	return (HEXBRUSH)hBrush;
}

HEXBRUSH _brush_createfromcanvas2(HEXCANVAS hCanvas, DWORD alpha) {
	canvas_s* pCanvas = nullptr;
	INT nError = 0;
	ID2D1BitmapBrush* hBrush = nullptr;
	if (_handle_validate(hCanvas, HT_CANVAS, (LPVOID*)&pCanvas, &nError))
	{
		ID2D1DeviceContext* pContext = _cv_context(pCanvas);
		D2D1_BITMAP_BRUSH_PROPERTIES bitmapBrushProperties = { };
		D2D1_BRUSH_PROPERTIES brushProperties = { 0 };
		brushProperties.opacity = (FLOAT)alpha / 255;
		brushProperties.transform.m11 = 1.0;
		brushProperties.transform.m22 = 1.0;
		bitmapBrushProperties.extendModeX = D2D1_EXTEND_MODE_WRAP;
		bitmapBrushProperties.extendModeY = D2D1_EXTEND_MODE_WRAP;
		bitmapBrushProperties.interpolationMode = D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR;
		pContext->CreateBitmapBrush((ID2D1Bitmap*)_cv_dx_bmp(pCanvas), bitmapBrushProperties, brushProperties, &hBrush);
	}
	return (HEXBRUSH)hBrush;
}

HEXBRUSH _brush_createfromcanvas(HEXCANVAS hCanvas)
{
	canvas_s* pCanvas = nullptr;
	INT nError = 0;
	ID2D1BitmapBrush* hBrush = nullptr;
	if (_handle_validate(hCanvas, HT_CANVAS, (LPVOID*)&pCanvas, &nError))
	{
		ID2D1DeviceContext* pContext = _cv_context(pCanvas);
		D2D1_BITMAP_BRUSH_PROPERTIES bitmapBrushProperties = {};
		bitmapBrushProperties.extendModeX = D2D1_EXTEND_MODE_WRAP;
		bitmapBrushProperties.extendModeY = D2D1_EXTEND_MODE_WRAP;
		bitmapBrushProperties.interpolationMode = D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR;
		pContext->CreateBitmapBrush((ID2D1Bitmap*)_cv_dx_bmp(pCanvas), bitmapBrushProperties, &hBrush);
	}
	return (HEXBRUSH)hBrush;
}

void _brush_settransform(HEXBRUSH hBrush, HEXMATRIX matrix)
{
	D2D1::Matrix3x2F mx = { };
	_matrix_init(&mx, matrix);
	((ID2D1BitmapBrush*)hBrush)->SetTransform(&mx);
}

HEXBRUSH _brush_createlinear_ex(FLOAT xStart, FLOAT yStart, FLOAT xEnd, FLOAT yEnd, const INT* arrStopPts, INT cStopPts)
{
	if (cStopPts < 2)
	{
		return NULL;
	}
	ID2D1GradientStopCollection* gradientStopCollection = nullptr;
	ID2D1LinearGradientBrush* hBrush = nullptr;
	D2D1_GRADIENT_STOP* gradientStops = (D2D1_GRADIENT_STOP*)malloc(cStopPts * sizeof(D2D1_GRADIENT_STOP));
	D2D1_LINEAR_GRADIENT_BRUSH_PROPERTIES gradientProperties{};
	if (gradientStops)
	{
		for (INT i = 0; i < cStopPts; i++)
		{
			ARGB2ColorF(arrStopPts[i* cStopPts+1], &gradientStops[i].color);
			gradientStops[i].position = (FLOAT)arrStopPts[i* cStopPts];
		}
		g_Ri.pD2DDeviceContext->CreateGradientStopCollection(gradientStops, cStopPts, D2D1_GAMMA_2_2, D2D1_EXTEND_MODE_CLAMP, &gradientStopCollection);

		gradientProperties.startPoint.x = xStart;
		gradientProperties.startPoint.y = yStart;
		gradientProperties.endPoint.x = xEnd;
		gradientProperties.endPoint.y = yEnd;
		if (gradientStopCollection)
			g_Ri.pD2DDeviceContext->CreateLinearGradientBrush(&gradientProperties, NULL, gradientStopCollection, &hBrush);

		free(gradientStops);
		return hBrush;
	}
	return NULL;
}

HEXBRUSH _brush_createlinear(FLOAT xStart, FLOAT yStart, FLOAT xEnd, FLOAT yEnd, EXARGB crBegin, EXARGB crEnd)
{
	INT arrStopPts[] = { 0, crBegin, 1, crEnd };
	return _brush_createlinear_ex(xStart, yStart, xEnd, yEnd, arrStopPts, 2);
}